package win.larryzeal.jmx;

/**
 * Hello world!
 */

import com.sun.jdmk.comm.HtmlAdaptorServer;
import win.larryzeal.jmx.mbean.standard.Hello;
import win.larryzeal.jmx.mbean.standard.Nana;
import win.larryzeal.jmx.mbean.standard.listener.HelloListener;

import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

/**
 * agent level: MBeanServer
 */
public class HelloAgent {
	public static void main(String[] args) throws MalformedObjectNameException,
			NotCompliantMBeanException, InstanceAlreadyExistsException,
			MBeanRegistrationException, IOException{
		// 下面这种方式不能在JConsole中使用
		//      MBeanServer server = MBeanServerFactory.createMBeanServer();

		// 【】首先建立一个MBeanServer，用来管理我们的MBean。
		// 通常是通过MBeanServer来获取我们MBean的信息，间接调用MBean的方法，然后生成我们的资源的一个对象。
		MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();

		String domainName = "my_domain_name";

		//【】为MBean（下面的new Hello()）创建ObjectName实例
		ObjectName helloName = new ObjectName(domainName + ":name=HelloWorld"); //格式固定
		// 【】将new Hello()这个对象注册到MBeanServer上去
		Hello hello = new Hello();
		mBeanServer.registerMBean(hello, helloName);

		// Distributed Layer
		// 【】提供一个HtmlAdaptor。支持Http访问协议，并且有一个不错的HTML界面，这里的Hello就是用这个作为远端管理的界面
		// 事实上HtmlAdaptor是一个简单的HttpServer，它将Http请求转换为JMX Agent的请求
		ObjectName adapterName = new ObjectName(domainName + ":name=htmladapter,port=8082");
		HtmlAdaptorServer adapter = new HtmlAdaptorServer();
		adapter.start();
		mBeanServer.registerMBean(adapter, adapterName);//这个，必须吗？我擦，还真是必须！为啥

		// 再提供一个connector，用于远程访问
		//可以通过JConsole作为客户端来管理MBean. 打开JConsole，在远程进程中输入rmi地址“service:jmx:rmi:///jndi/rmi://localhost:1099/my_domain_name”
		int rmiPort = 1099;
		//Creates and exports a Registry instance on the local host that accepts requests on the specified port.
		//其他的解决办法：运行 %JAVA_HOME%/bin/rmiregistry.exe 1099就有和这行代码一样的效果。
		Registry registry = LocateRegistry.createRegistry(rmiPort);//可以在某一特定端口创建名字服务，从而无需再手工启动rmiregistry

		JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" + rmiPort + "/" + domainName);//创建URL
		JMXConnectorServer jmxConnector = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mBeanServer);//将URL和MBeanServer绑定
		jmxConnector.start();


		// 新注册一个MBean
		Nana nana = new Nana();
		mBeanServer.registerMBean(nana, new ObjectName(domainName + ":name=nana"));
		nana.addNotificationListener(new HelloListener(), null, new Hello());//为nana添加监听器、过滤器、以及回调对象
//		adapter.start(); //要放这里吗？
	}
}
